package edu.csu.smartpark.service.Impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import edu.csu.smartpark.dao.WorkOrderDAO;
import edu.csu.smartpark.dao.WorkOrderOperationRecordDAO;
import edu.csu.smartpark.model.DO.BaseDO.BaseWorkOrderSpecific;
import edu.csu.smartpark.model.DO.RepairWorkOrderDO;
import edu.csu.smartpark.model.DO.WorkOrderDO;
import edu.csu.smartpark.model.DO.WorkOrderOperationRecordDO;
import edu.csu.smartpark.model.DTO.WorkOrderOperationRecordQueryDTO;
import edu.csu.smartpark.model.DTO.WorkOrderQueryDTO;
import edu.csu.smartpark.model.PO.WorkOrderOperationRecordPO;
import edu.csu.smartpark.model.PO.WorkOrderPO;
import edu.csu.smartpark.model.VO.PageVO;
import edu.csu.smartpark.model.VO.WorkOrderVO;
import edu.csu.smartpark.model.common.BusinessException;
import edu.csu.smartpark.service.WorkOrderService;
import edu.csu.smartpark.util.Constants;
import edu.csu.smartpark.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.LinkedList;
import java.util.List;

@Service
@Slf4j
public class WorkOrderServiceImpl implements WorkOrderService {

    @Autowired
    private WorkOrderDAO workOrderDAO;

    @Autowired
    private WorkOrderOperationRecordDAO workOrderOperationRecordDAO;

    @Override
    public String createWorkOrder(WorkOrderDO workOrderDO) throws BusinessException {
        WorkOrderPO workOrderPO = new WorkOrderPO();
        BeanUtils.copyProperties(workOrderDO, workOrderPO);
        String workOrderSpecific = JSONObject.toJSONString(workOrderDO.getWorkOrderSpecific());
        workOrderPO.setWorkOrderSpecific(workOrderSpecific);
        int row = workOrderDAO.insert(workOrderPO);
        if (row == 0){
            log.error("insert work order {} error", workOrderPO.getId());
            throw new BusinessException(BusinessException.INTERNAL_SERVER_ERROR, "insert work order fail");
        }
        return workOrderPO.getId();
    }

    @Override
    public int updateWorkOrder(WorkOrderDO workOrderDO) throws BusinessException{
        if (workOrderDO == null){
            log.warn("work order params is null");
            throw new BusinessException(BusinessException.PARAMETERERROR, "work order params is null");
        }
        WorkOrderPO workOrderPO  = workOrderDAO.selectById(workOrderDO.getId());
        if (workOrderPO == null){
            log.warn("work order {} is not exist", workOrderDO.getId());
            throw new BusinessException(BusinessException.PARAMETERERROR, "work order is not exist");
        }
        String workOrderSpecific = workOrderPO.getWorkOrderSpecific();
        BaseWorkOrderSpecific baseWorkOrderSpecific = workOrderDO.getWorkOrderSpecific();
        workOrderPO.setWorkOrderSpecific(baseWorkOrderSpecific.updateSpecific(workOrderSpecific));
        int row = workOrderDAO.updateById(workOrderPO);
        return row;
    }

    @Override
    public int deleteWorkOrder(String id) {
        UpdateWrapper<WorkOrderPO> wrapper = new UpdateWrapper<>();
        wrapper.eq("id", id).set("is_deleted", 1);
        int row  = workOrderDAO.update(null, wrapper);
        return row;
    }

    @Override
    public PageVO<WorkOrderVO> queryWorkOrder(WorkOrderQueryDTO workOrderQueryDTO) {
        QueryWrapper<WorkOrderPO> wrapper = new QueryWrapper<>();
        if (!StringUtil.isEmpty(workOrderQueryDTO.getId())){
            wrapper.eq("id", workOrderQueryDTO.getId());
        }
        if (!StringUtil.isEmpty(workOrderQueryDTO.getApplicantName())){
            wrapper.eq("applicant_name", workOrderQueryDTO.getApplicantName());
        }
        if (!StringUtil.isEmpty(workOrderQueryDTO.getApplicantPhone())){
            wrapper.eq("applicant_phone", workOrderQueryDTO.getApplicantPhone());
        }
        if (!StringUtil.isEmpty(workOrderQueryDTO.getApplicantId())){
            wrapper.eq("applicant_id", workOrderQueryDTO.getApplicantId());
        }
        if (!StringUtil.isEmpty(workOrderQueryDTO.getParkId())){
            wrapper.eq("park_id", workOrderQueryDTO.getParkId());
        }
        if (workOrderQueryDTO.getTypeCode() != null){
            wrapper.eq("type_code", workOrderQueryDTO.getTypeCode());
        }
        if (workOrderQueryDTO.getState() != null){
            wrapper.in("state", workOrderQueryDTO.getState());
        }
        if (workOrderQueryDTO.getPageNum() == null){
            workOrderQueryDTO.setPageNum(1);
        }
        if (workOrderQueryDTO.getPageSize() == null){
            workOrderQueryDTO.setPageSize(10);
        }
        Page<WorkOrderPO> page = new Page<>(workOrderQueryDTO.getPageNum(), workOrderQueryDTO.getPageSize());
        IPage<WorkOrderPO> workOrderPOIPage = workOrderDAO.selectPage(page, wrapper);
        List<WorkOrderVO> workOrderVOS = new LinkedList<>();
        for (WorkOrderPO workOrderPO : workOrderPOIPage.getRecords()){
            WorkOrderVO workOrderVO = new WorkOrderVO();
            BeanUtils.copyProperties(workOrderPO, workOrderVO);
            if (workOrderPO.getTypeCode() == Constants.RepairWorkOrder){
                RepairWorkOrderDO repairWorkOrderDO = JSONObject.parseObject(workOrderPO.getWorkOrderSpecific(), RepairWorkOrderDO.class);
                workOrderVO.setWorkOrderSpecific(repairWorkOrderDO);
            }
            workOrderVOS.add(workOrderVO);
        }
        PageVO<WorkOrderVO> res = new PageVO<>();
        res.setPageNum(workOrderPOIPage.getCurrent());
        res.setPageSize(workOrderPOIPage.getSize());
        res.setPages(workOrderPOIPage.getPages());
        res.setTotal(workOrderPOIPage.getTotal());
        res.setRecords(workOrderVOS);
        return res;
    }

    @Override
    public String createWorkOrderOperationRecord(WorkOrderOperationRecordDO workOrderOperationRecordDO) throws BusinessException {
        if (workOrderOperationRecordDO == null){
            log.warn("work order operation record is null");
            throw new BusinessException(BusinessException.PARAMETERERROR, "work order operation record is null");
        }
        // 更新工单状态
        WorkOrderPO workOrderPO = workOrderDAO.selectById(workOrderOperationRecordDO.getWorkOrderId());
        if (workOrderPO == null){
            log.info("update work order operation {} fail, work order {} is not exist", workOrderOperationRecordDO.getOperationType(), workOrderOperationRecordDO.getWorkOrderId());
            throw new BusinessException(BusinessException.PARAMETERERROR, "operate work order fail, because work order is not exist");
        }
        switch(workOrderOperationRecordDO.getOperationType()){
            case 1: workOrderPO.setState(Constants.WorkOrderStatusPending); break;
            case 2: workOrderPO.setState(Constants.WorkOrderStatusProcessing); break;
            case 3: workOrderPO.setState(Constants.WorkOrderStatusProcessed); break;
            case 4: workOrderPO.setState(Constants.WorkOrderStatusCanceled); break;
        }
        workOrderDAO.updateById(workOrderPO);
        WorkOrderOperationRecordPO workOrderOperationRecordPO = new WorkOrderOperationRecordPO();
        BeanUtils.copyProperties(workOrderOperationRecordDO, workOrderOperationRecordPO);
        int row = workOrderOperationRecordDAO.insert(workOrderOperationRecordPO);
        if (row == 0){
            log.error("create work order operation record {} fail", workOrderOperationRecordPO.getId());
            throw new BusinessException(BusinessException.INTERNAL_SERVER_ERROR, "create work order operation record fail");
        }
        return workOrderOperationRecordPO.getId();
    }

    @Override
    public List<WorkOrderOperationRecordDO> getWorkOrderOperationRecords(WorkOrderOperationRecordQueryDTO workOrderOperationRecordQueryDTO) {
        if (workOrderOperationRecordQueryDTO == null){
            log.warn("work order operation record query dto is null");
            throw new BusinessException(BusinessException.PARAMETERERROR, "work order operation record query dto is null");
        }
        QueryWrapper<WorkOrderOperationRecordPO> wrapper = new QueryWrapper<>();
        if (!StringUtil.isEmpty(workOrderOperationRecordQueryDTO.getId())){
            wrapper.eq("id", workOrderOperationRecordQueryDTO.getId());
        }
        if (!StringUtil.isEmpty(workOrderOperationRecordQueryDTO.getWorkOrderId())){
            wrapper.eq("work_order_id", workOrderOperationRecordQueryDTO.getWorkOrderId());
        }
        if (workOrderOperationRecordQueryDTO.getOperationType() != null){
            wrapper.eq("operation_type", workOrderOperationRecordQueryDTO.getOperationType());
        }
        List<WorkOrderOperationRecordPO> workOrderOperationRecordPOS = workOrderOperationRecordDAO.selectList(wrapper);
        List<WorkOrderOperationRecordDO> workOrderOperationRecordDOS = new LinkedList<>();
        for (WorkOrderOperationRecordPO workOrderOperationRecordPO : workOrderOperationRecordPOS){
            WorkOrderOperationRecordDO workOrderOperationRecordDO = new WorkOrderOperationRecordDO();
            BeanUtils.copyProperties(workOrderOperationRecordPO, workOrderOperationRecordDO);
            workOrderOperationRecordDOS.add(workOrderOperationRecordDO);
        }
        return workOrderOperationRecordDOS;
    }
}
